package com.zxy.ziems.server.storage.service.imp;

import cn.hutool.core.collection.CollectionUtil;
import com.zxy.ziems.common.pojo.MeasureDataBean;
import com.zxy.ziems.server.board.constant.BoardConstant;
import com.zxy.ziems.server.constant.enums.DeviceStatusDictItemEnum;
import com.zxy.ziems.server.constant.enums.DictCodeEnum;
import com.zxy.ziems.server.device.convertor.DeviceConvertor;
import com.zxy.ziems.server.device.pojo.entity.DataTypeEntity;
import com.zxy.ziems.server.device.pojo.entity.DeviceEntity;
import com.zxy.ziems.server.device.pojo.entity.DeviceExtendEntity;
import com.zxy.ziems.server.device.pojo.entity.DevicePropertyEntity;
import com.zxy.ziems.server.device.service.DataTypeService;
import com.zxy.ziems.server.device.service.DeviceExtendService;
import com.zxy.ziems.server.device.service.DevicePropertyService;
import com.zxy.ziems.server.device.service.DeviceService;
import com.zxy.ziems.server.domain.DeviceMeasureData;
import com.zxy.ziems.server.domain.DictItem;
import com.zxy.ziems.server.energy.mapper.DeviceMeasureDataMapper;
import com.zxy.ziems.server.energy.pojo.entity.DeviceMeasureDataHistoryEntity;
import com.zxy.ziems.server.energy.service.DeviceMeasureDataHistoryService;
import com.zxy.ziems.server.mybatis.core.service.ServiceImplX;
import com.zxy.ziems.server.service.DictItemService;
import com.zxy.ziems.server.storage.pojo.MeasureDataAddDTO;
import com.zxy.ziems.server.storage.pojo.MeasureDataValueDTO;
import com.zxy.ziems.server.storage.service.MeasureDataStorageService;
import com.zxy.ziems.server.utils.AssertUtil;
import com.zxy.ziems.server.utils.BusinessExceptionUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.rmi.ServerException;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author 10348359
 * @create 2024-04-29 22:07
 */
@Service
@Slf4j
public class MeasureDataStorageServiceImpl extends ServiceImplX<DeviceMeasureDataMapper, DeviceMeasureData>
        implements MeasureDataStorageService {

    @Autowired
    private DeviceService deviceService;
    @Autowired
    private DataTypeService dataTypeService;
    @Autowired
    private DeviceExtendService deviceExtendService;
    @Autowired
    private DictItemService dictItemService;
    @Autowired
    private DevicePropertyService devicePropertyService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void storageMeasureDataList(List<MeasureDataBean> list) {
        if (CollectionUtil.isEmpty(list)) {
            return;
        }
        List<DeviceMeasureData> dataList = new ArrayList<>(list.size());
        List<DeviceMeasureDataHistoryEntity> historyEntityList = new ArrayList<>(list.size());

        list.forEach((item) -> {

            DeviceMeasureData d = makeMeasureDataBy(item);

            if (Objects.isNull(d)) {
                return;
            }
            DeviceMeasureDataHistoryEntity h = makeMeasureDataBy(d);
            dataList.add(d);

            historyEntityList.add(h);
        });
        if (CollectionUtil.isEmpty(dataList)) {
            return;
        }
        baseMapper.batchSaveEntityList(dataList);
        historyService.saveBatch(historyEntityList);
    }

    @Override
    @Transactional
    public void storageMeasureData(MeasureDataAddDTO measureDataAddDTO) throws ServerException {
        AssertUtil.nonNull(measureDataAddDTO, "参数不可为空");
        List<DeviceMeasureData> dataList = new ArrayList<>();
        List<DeviceMeasureDataHistoryEntity> historyEntityList = new ArrayList<>();

        DeviceEntity device = deviceService.getById(measureDataAddDTO.getDeviceId());
        AssertUtil.nonNull(device, "未找到设备或设备已被删除");
        List<MeasureDataValueDTO> measureDataValueDTOList = measureDataAddDTO.getMeasureDataValueDTOList();

        if (measureDataValueDTOList.isEmpty()) {
            throw new ServerException("measureDataValueDTOList is null");
        }

        List<String> dataTypeIds = measureDataValueDTOList.stream().map(m -> m.getDataTypeId()).distinct().collect(Collectors.toList());
        final List<DataTypeEntity> dataTypeEntityList = dataTypeService.listByIdList(dataTypeIds);


        for (MeasureDataValueDTO measureDataValueDTO : measureDataValueDTOList) {
            MeasureDataBean bean = new MeasureDataBean();
            bean.setDeviceId(measureDataAddDTO.getDeviceId());
            bean.setDataTypeId(measureDataValueDTO.getDataTypeId());
            bean.setMeasureValue(measureDataValueDTO.getMeasureValue());
            bean.setMeasureTime(LocalDateTime.now());

            final DataTypeEntity dataTypeEntity = dataTypeEntityList.stream().filter(m -> m.getId().equals(measureDataValueDTO.getDataTypeId())).findFirst().orElse(null);

            AssertUtil.nonNull(dataTypeEntity, "未找到设备属性");

            DevicePropertyEntity devicePropertyEntity = devicePropertyService.getBy(measureDataAddDTO.getDeviceId(), measureDataValueDTO.getDataTypeId());
            bean.setUnitId(devicePropertyEntity == null ? "0" : devicePropertyEntity.getUnitId());

            if (dataTypeEntity.getGroupLevel1Name().equals("设备属性")) {
                // 如果设备状态，修改设备的状态，否则增加属性
                if (dataTypeEntity.getCode().equals(BoardConstant.DeviceExtendDataCodeEnum.OPERATIONAL_STATUS.getTypeCode())) {
                    // 获取设备运行状态
                    List<DictItem> statusItems = dictItemService.getByDictCode(DictCodeEnum.OPERATIONAL_STATUS.getCode());
                    Map<String, String> statusMap = statusItems.stream().collect(Collectors.toMap(DictItem::getItemId, DictItem::getItemCode));
                    String status = statusMap.get(measureDataValueDTO.getMeasureValue());
                    device.setOnlineStatus(DeviceStatusDictItemEnum.getOnlineStatus(status));
                    deviceService.updateBy(device);
                } else {
                    DeviceExtendEntity deviceExtendEntity = DeviceConvertor.INSTANCE.measureDataBean2DeviceExtendEntity(bean);
                    deviceExtendService.insertOrUpdate(deviceExtendEntity);
                }
                continue;
            } else {
                try {
                    new BigDecimal(bean.getMeasureValue());
                } catch (Exception e) {
                    log.warn("测量值错误，val={}", bean.getMeasureValue());
                    throw BusinessExceptionUtil.exception("测量值输入有误");
                }

            }

            DeviceMeasureData d = makeMeasureDataBy(bean);
            if (Objects.isNull(d)) {
                continue;
            }
            DeviceMeasureDataHistoryEntity h = makeMeasureDataBy(d);
            dataList.add(d);

            historyEntityList.add(h);


        }
        baseMapper.batchSaveEntityList(dataList);
        historyService.saveBatch(historyEntityList);
    }


    private DeviceMeasureData makeMeasureDataBy(MeasureDataBean bean) {
        DeviceMeasureData d = new DeviceMeasureData();
        d.setMeasureValue(new BigDecimal(bean.getMeasureValue()));
        d.setDataTypeId(bean.getDataTypeId());
        d.setMeasureTime(bean.getMeasureTime());
        d.setDeviceId(bean.getDeviceId());
        d.setUnitId(bean.getUnitId());
        return d;
    }

    private DeviceMeasureDataHistoryEntity makeMeasureDataBy(DeviceMeasureData bean) {
        DeviceMeasureDataHistoryEntity d = new DeviceMeasureDataHistoryEntity();
        d.setMeasureValue(bean.getMeasureValue());
        d.setDataTypeId(bean.getDataTypeId());
        d.setMeasureTime(bean.getMeasureTime());
        d.setDeviceId(bean.getDeviceId());
        d.setUnitId(bean.getUnitId());
        return d;
    }

    private DeviceMeasureDataHistoryService historyService;

    @Autowired
    public void setHistoryService(DeviceMeasureDataHistoryService historyService) {
        this.historyService = historyService;
    }
}
